#pragma once

#include <chrono>
#include <string>
#include <memory>
#include <ostream>
#include <iostream>
namespace IntegralLib
{
	class Benchmarker
	{
	protected:
		using BenchTimer = std::chrono::high_resolution_clock;
		using BenchPoint = std::chrono::time_point<BenchTimer>;

		BenchPoint Start = BenchTimer::now();
		BenchPoint End;
		bool Stopped = false;

	public:
		// 随便用来存储什么东西的 UserData 用于回调函数
		std::shared_ptr<void> UserData = nullptr;

		// 析构时是否汇报计时结果
		bool EnableReport = true;

		// 停止计时
		void Stop(bool DoReport);

		// 获取时间间隔
		double GetDurationS();
		int64_t GetDurationNS();
		int64_t GetDurationUS();
		int64_t GetDurationMS();

		// 回调函数：计时器停止计时时调用。如果 Enable == false 则不会调用。
		void (*OnReport)(void* UserData, double DurationSeconds);

		Benchmarker();
		~Benchmarker();

		Benchmarker(bool DoReport, std::shared_ptr<void> UserData, void (*ReportFunc)(void* UserData, double DurationSeconds));

		struct EasyReportData
		{
			std::string PrintfFormat = "[INFO] Time usage is %lg seconds\n";
			int HowManyTimesUseDurationLF = 1;
			double Multiply = 1000;
			std::ostream* LogTo = &std::cout;
		};

		Benchmarker(bool DoReport, const EasyReportData& UserData);
	};
}
